task
在数学中,一个数n的阶乘写作n!,且定义如下:
$n! = 1 × 2 × 3 × 4 × $• • • $× (n − 1) × n =\prod_{i=1}^N i$
0!被认为是1。n!将会随着n迅速增长。如下一些数的阶乘:
0! = 1 5! = 120
1! = 1 10! = 3628800
2! = 2 14! = 87178291200
3! = 6 18! = 6402373705728000
4! = 24 22! = 1124000727777607680000
通过观察可以发现,有些数的阶乘末尾中有奇数个零(即5!和18!),而有些数的阶乘的末尾中有偶数个零(即0!,10!,20!)。那么问题来了,给定一个数n,求在1~n中有多少数的阶乘的末尾有偶数个0?
$n<=10^{18}$
solution
首先我们需要知道怎样的数字的阶乘是可以有偶数个零。
肯定是是由偶数个10相乘,而10=2*5,所以我们只用统计2和5的因子的个数,看一下它们是否能够组成偶数个10,那么10的个数一定是根据个数较少的那个因子判定的,而在一个数的阶乘当中因子2的个数总是不少于5的,所以我们就只用统计n的阶乘中5的个数。
那么怎么统计呢?最暴力的写法就是用字母那题的方法判断,一个数我们可以算的很快,但是我们需要1~n的所有的数的阶乘中因子5的个数,而n最大可达$10^{18}$,显然会超时。
原先我想着用数学的方法去写,但是随着想法越来越复杂,只能放弃。
对于判断一个数的阶乘是否有偶数个5,正解有更好的方法:以530为例,我们将其转化为5进制,即4110,而1~530中为5的倍数的数用411(5进制)个,为25的倍数的有41(5进制)个,为125的倍数的有4(5进制)个,那么我们可以发现当411的每一位数字之和为偶数的话,那么1~530中就有偶数个数为5的倍数。25,和125都可以以此类推。
所以接下来我们就可以用数位dp来计算个数了。
$dp[f][p][pre][x]$表示当前数字是第x位时,前面几位上的数字这和的末位的奇偶性为pre,p为前面几位时的pre之和的奇偶性。如果前面有一位的数字是小于n那一位上的数字,那么接下来取什么数字,都将小于n,所以我们需要一个f,来判断当前数字是否可以随便取。
记忆化搜索的边界是但x<0时,只有p=0时,才说明是有偶数个5,我们返回一个1.
Code
1 |
|